﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace Delegates
{

    public delegate void MyCallback(string s);
    class Program
    {
        static void Main(string[] args)
        {
            CallbackDemonstration(new MyCallback(Print));
            CallbackDemonstration(new MyCallback(PrintTrim));

            //the same with Action<T>
            CallbackAction(new Action<string>(Print));
            CallbackAction(new Action<string>(PrintTrim));

            //Func delegate demo
            var result = CallbackFunc(new Func<string, int>(Count));
            Console.WriteLine(result);

            MyCallback cb1 = new MyCallback(Print);
            MyCallback cb2 = new MyCallback(PrintTrim);
            cb1 += cb2;

            cb1("  foo");

            TestPrint();

            TestLambda();

            TestEvent();

            Console.ReadKey();
        }

        private static void TestEvent()
        {
            var printer = new Printer();
            printer.PrintStarted += () => { Console.WriteLine("Print Started."); };
            printer.PrintFinished += (sender, e) => { Console.WriteLine("Print Finished"); };
            printer.Printing += (sender, e) => { Console.WriteLine("Printing page" + e.CurrentPage); };
            printer.Print();
        }



        private static void TestLambda()
        {
            Action<string> del1 = s => Console.WriteLine(s);

            Action<string, string> del2 = (s1, s2) =>
            {
                string s = s1 + s2;
                Console.WriteLine(s);
            };

            Func<string, string> func1 = s => s.Trim();

            string[] ss = { "Hello", "World", "Hello", "foo", "bar" };
            int maxL = ss.Max(s => s.Length);
            string[] d = ss.Distinct().ToArray();

            int[] n = { 1, 2, 5, 78, 14, 35 };
            n.Max(s => s); // n.Max();


        }

        static void TestPrint()
        {
            Print1 p1 = new Print1();
            Print2 p2 = new Print2();

            CallbackAction(new Action<string>(p1.Print));
            CallbackAction(new Action<string>(p2.Print));
            CallbackAction(new Action<string>(Print));

            DoPrint(p1);
            DoPrint(p2);
        }

        static void DoPrint(IPrint p)
        {
            p.Print("foo");
        }

        static void Print(string s)
        {
            Console.WriteLine(s);
        }

        static void PrintTrim(string s)
        {
            Console.WriteLine(s.Trim());
        }

        static int Count(string s)
        {
            return s.Length;
        }

        static void CallbackDemonstration(MyCallback callback)
        {
            string data = "   Hello";
            callback(data);
        }

        static void CallbackAction(Action<string> callback)
        {
            string data = "   Hello";
            callback(data);
        }

        static int CallbackFunc(Func<string, int> callback)
        {
            string data = "World";
            return callback(data);
        }
    }
}
